// +build ignore

//#include "common.h"
#include "vmlinux.h"
#include "bpf_helpers.h"
#include "bpf_endian.h"
#include <iproute2/bpf_elf.h>
//#include "maps.h"
#define ETH_P_8021Q        0x8100          /* 802.1Q VLAN Extended Header  */
#define ETH_P_IPV6        0x86DD                /* IPv6 over bluebook                */
#define 	ETH_P_8021AD   0x88A8 /* 802.1ad Service VLAN */
#define CONDITIONAL_PREALLOC 0
#define ETH_P_IP	0x0800
//bpf_elf_map
//bpf_map_def
// struct bpf_elf_map hash_map __section("maps") = {
// 	.type       = BPF_MAP_TYPE_HASH,
// 	.size_key   = sizeof(uint32_t),
// 	.size_value = sizeof(uint64_t),
// 	.max_elem   = 2,
// 	.pinning    = PIN_GLOBAL_NS,
// };

// struct bpf_map_def SEC("maps") blacklist = {
//     .type = BPF_MAP_TYPE_HASH,
//     .key_size = sizeof(u32),
//     .value_size = sizeof(u32),
//     .max_entries = 1024,
//     //.pinning = PIN_GLOBAL_NS,
//     //.namespace = "globals",
// };
struct bpf_elf_map SEC("maps") blacklist = {
    .type = BPF_MAP_TYPE_HASH,
    .size_key = sizeof(u32),
    .size_value = sizeof(u32),
    .max_elem       = 1024,
     .pinning        = PIN_GLOBAL_NS,
};


/* helper functions called from eBPF programs */
// static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
// 	        (void *) BPF_FUNC_trace_printk;

/* macro for printing debug info to the tracing pipe, useful just for
 debugging purposes and not recommended to use in production systems.

 use `sudo cat /sys/kernel/debug/tracing/trace_pipe` to read debug info.
 */
#define printt(fmt, ...)                                                   \
            ({                                                             \
                char ____fmt[] = fmt;                                      \
                bpf_trace_printk(____fmt, sizeof(____fmt), ##__VA_ARGS__); \
            })

SEC("xdp")
int xdp_ip_filter(struct xdp_md *ctx) {
    void *end = (void *)(long)ctx->data_end;
    void *data = (void *)(long)ctx->data;
    u32 ip_src;
    u64 offset;
    u16 eth_type;

    struct ethhdr *eth = data;
    offset = sizeof(*eth);

    if (data + offset > end) {
        return XDP_ABORTED;
    }
    eth_type = eth->h_proto;

    /* handle VLAN tagged packet */
    if (eth_type == bpf_ntohs(ETH_P_8021Q) || eth_type == bpf_ntohs(ETH_P_8021AD)) {
	struct vlan_hdr *vlan_hdr;

	vlan_hdr = (void *)eth + offset;
	offset += sizeof(*vlan_hdr);
	if ((void *)eth + offset > end)
		return false;
	eth_type = vlan_hdr->h_vlan_encapsulated_proto; 
   }

    /* let's only handle IPv4 addresses */
    if (eth_type !=bpf_ntohs(ETH_P_IP)) {
        return XDP_PASS;
    }
    data += sizeof(*eth);
    struct iphdr *iph = data;
    if (data + sizeof(*iph) > end){
        return XDP_ABORTED;
    }
    
    ip_src = iph->saddr;

    if (bpf_map_lookup_elem(&blacklist, &ip_src)) {
        return XDP_DROP;
    }

    return XDP_PASS;
}

char __license[] SEC("license") = "Dual MIT/GPL";
